package com.example.demo.system.service.impl;

import com.example.demo.common.exception.FileUploadException;
import com.example.demo.system.entity.FItem;
import com.example.demo.system.service.IFileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

@Slf4j
@Service
public class FileService implements IFileService {
// TODO 数据库或者别的位置。。。
    @Value("${czh.file.basepath}")
    String BASE_PATH;
    @Value("${czh.file.slice.basepath}")
    String SLICE_BASE_PATH;

    String SEPARATOR = File.separator;
    @Override
    public void save(MultipartFile file,String path) {

        File f = getFile(file.getOriginalFilename(), path);
        try {
            f.createNewFile();
            FileOutputStream fileOutputStream = new FileOutputStream(f);
            pipe(file.getInputStream(), fileOutputStream);
        }catch (Exception e){
            throw new FileUploadException("上传文件出错啦");
        }
    }

    @Override
    public void mkdir(String path, String dirName) {
        File f = getFile(dirName,path);
        boolean mkdir = f.mkdir();
        if (!mkdir) {
            throw new RuntimeException("创建失败！！");
        }
    }

    @Override
    public List<FItem> getCurrentItems(String dirname) {

        // this is new b
//        File file = new File(BASE_PATH + dirname);
        File file = getFile("", dirname);
        File[] files = file.listFiles();

        List<FItem> list = new ArrayList<>();
        for (File f : files) {
            list.add(new FItem(f.getName(),f.isDirectory(),""));
        }
        return list;
    }

    @Override
    public void rename(String oldName, String newName, String path) {
        File file = getExistFile(oldName, path);
        if (!file.exists()) {
            throw new RuntimeException("文件不存在");
        }
        File existFile = getExistFile(newName, path);
        if (existFile.exists()) {
            throw new RuntimeException("文件名重复！");
        }
        boolean rename = file.renameTo(existFile);
        if (!rename) {
            throw new RuntimeException("文件名 重复！！！");
        }
    }

    // 有BUG from 需要处理 解析出 文件名 解决了。。
    @Override
    public void mv(String from, String to, String path) {
        File f = getExistFile(from, path);
        File t = getFile(to + File.separator + from, path);//
        if (t.exists()) {
            throw new RuntimeException("文件存在!😬");
        }
        try {
            Files.move(f.toPath(), t.toPath());
        } catch (IOException e) {
            e.printStackTrace();
            throw new RuntimeException("移动文件失败！");
        }
    }

    @Override
    public void cacheSlice(MultipartFile blob, String sliceFileName) {
        File file = getCacheFile(sliceFileName);
        try {
            FileOutputStream fileOutputStream = new FileOutputStream(file);
//            fileOutputStream.write(blob.getBytes());
            pipe(blob.getInputStream(),fileOutputStream);
        }catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("分片存储失败");
        }
    }

    @Override
    public void coalesce(String path, String sliceFileName, String fileName, int sliceTotalNumber) {
        File file;


        try {
            synchronized (FileService.class) {
                file = getFile(fileName,path);
                file.createNewFile();
            }

            FileInputStream fileInputStream;

            FileOutputStream fileOutputStream = new FileOutputStream(file);
            for (int i = 0; i < sliceTotalNumber; i++) {
                File cacheFile = getCacheFile(sliceFileName + i);
                fileInputStream = new FileInputStream(cacheFile);
                pipe(fileInputStream,fileOutputStream);
                cacheFile.delete();
            }
        }catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException("合并文件失败!");
        }

    }

    @Override
    public void abort(String sliceFileName, Integer uploadedSlice) {
        for (int i = 0; i <= uploadedSlice; i++) {
            File cacheFile = getCacheFile(sliceFileName + i);
            boolean delete = cacheFile.delete();
        }
    }


    private void pipe(InputStream inputStream, FileOutputStream fileOutputStream) throws IOException {
        byte[] bytes = new byte[1024];
        int len;
        while ((len = inputStream.read(bytes)) != -1) {
            fileOutputStream.write(bytes, 0, len);
        }
    }

    private File getCacheFile(String sliceFileName) {

        String fullPath = SLICE_BASE_PATH + sliceFileName;

        File f = new File(fullPath);

        return f;
    }

    private File getExistFile(String name, String path) {
        String realPath = path.replaceAll(",", SEPARATOR);
        if(!realPath.isEmpty()) {
            realPath += SEPARATOR;
        }
        String fullPath = BASE_PATH + realPath  + name;
        File file = new File(fullPath);
        return file;
    }

    /**
     *
     * @param name 文件名 没有则为空
     * @param path 相对路径！！！！
     * @return
     */
    private File getFile(String  name, String path) {
        String realPath = path.replaceAll(",", SEPARATOR);

        if(!realPath.isEmpty()) {
            realPath += SEPARATOR;
        }

        String fullPath = BASE_PATH + realPath  + name;

        File f = new File(fullPath);
        if (!name.isEmpty() && f.exists()) {
             fullPath = BASE_PATH + realPath  + UUID.randomUUID() + name;
             f = new File(fullPath);
        }
        return f;
    }
}
